Fix the vnet module for Xen 3.1.x.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 7 Jun 2007 10:06:00 +0000 (11:06 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 7 Jun 2007 10:06:00 +0000 (11:06 +0100)
Signed-off-by: Robert Valentan <R.Valentan@solid-soft.at>
tools/vnet/vnet-module/esp.c
tools/vnet/vnet-module/etherip.c
tools/vnet/vnet-module/skb_util.h
tools/vnet/vnet-module/varp.c
tools/vnet/vnet-module/vnet_forward.c

index f18d1b1523c854eef1eb85704a285c283f55cbc0..4575110921121145c4eac1d3dbb75ee5c9eb2ef7 100644 (file)
@@ -341,12 +341,12 @@ static int esp_sa_send(SAState *sa, struct sk_buff *skb, Tunnel *tunnel){
         dprintf("> ETH header pull...\n");
         memmove(skb->data, skb->mac.raw, ETH_HLEN);
         skb->mac.raw = skb->data; 
-        __skb_pull(skb, ETH_HLEN);
+        skb_pull_vn(skb, ETH_HLEN);
     }
     dprintf("> IP header pull...\n");
     memmove(skb->data, skb->nh.raw, ip_n);
     skb->nh.raw = skb->data;
-    __skb_pull(skb, ip_n);
+    skb_pull_vn(skb, ip_n);
     esph = (void*)skb->data;
     // Add spi and sequence number.
     esph->spi = sa->ident.spi;
@@ -457,7 +457,7 @@ static int esp_sa_recv(SAState *sa, struct sk_buff *skb){
     // Move skb->data back to ethernet header.
     // Do in 2 moves to ensure offsets are +ve,
     // since args to skb_pull/skb_push are unsigned.
-    __skb_pull(skb, head_n);
+    skb_pull_vn(skb, head_n);
     __skb_push(skb, skb->data - skb->mac.raw);
     // After this esph is invalid.
     esph = NULL;
@@ -763,7 +763,7 @@ static int esp_protocol_recv(struct sk_buff *skb){
     dprintf(">\n");
 #ifdef DEBUG
     dprintf("> recv skb=\n"); 
-    skb_print_bits(skb, 0, skb->len);
+    skb_print_bits("", skb, 0, skb->len);
 #endif
     ip_n = (skb->nh.iph->ihl << 2);
     if(skb->data == skb->mac.raw){
@@ -773,7 +773,7 @@ static int esp_protocol_recv(struct sk_buff *skb){
             err = -EINVAL;
             goto exit;
         }
-        skb_pull(skb, eth_n + ip_n);
+        skb_pull_vn(skb, eth_n + ip_n);
     }
     addr = skb->nh.iph->daddr;
     err = esp_skb_header(skb, &esph);
index 3e531c7fbea0e949dcb828080717ef03bc2a95a9..f97099c3e7cc16bac0dff6a8a74213213281324c 100644 (file)
@@ -270,6 +270,7 @@ int etherip_protocol_recv(struct sk_buff *skb){
     u32 saddr, daddr;
     char vnetbuf[VNET_ID_BUF];
     struct ethhdr *eth;
+    struct sk_buff *newskb;
 
     dprintf(">\n");
     saddr = skb->nh.iph->saddr;
@@ -293,7 +294,7 @@ int etherip_protocol_recv(struct sk_buff *skb){
             err = -EINVAL;
             goto exit;
         }
-        skb_pull(skb, pull_n);
+        skb_pull_vn(skb, pull_n);
     }
     // Assume skb->data points at etherip header.
     etheriph = (void*)skb->data;
@@ -318,7 +319,18 @@ int etherip_protocol_recv(struct sk_buff *skb){
         goto exit;
     }
     // Point at the headers in the contained ethernet frame.
-    skb->mac.raw = skb_pull(skb, etherip_n);
+    skb->mac.raw = skb_pull_vn(skb, etherip_n);
+
+    newskb = alloc_skb(skb->len, GFP_ATOMIC);
+    if (!newskb) {
+        wprintf("> alloc new sk_buff failed \n");
+        goto exit;
+    }
+    newskb->mac.raw = skb_put(newskb, skb->len);
+    skb_copy_bits(skb, 0, newskb->data, skb->len);
+    kfree_skb(skb);
+    skb = newskb;
+
     eth = eth_hdr(skb);
 
     // Simulate the logic from eth_type_trans()
@@ -340,27 +352,12 @@ int etherip_protocol_recv(struct sk_buff *skb){
     
     // Assuming a standard Ethernet frame.
     // Should check for protocol? Support ETH_P_8021Q too.
-    skb->nh.raw = skb_pull(skb, ETH_HLEN);
-
-#ifdef __KERNEL__
-    // Fix IP options, checksum, skb dst, netfilter state.
-    memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-    if (skb->ip_summed == CHECKSUM_HW){
-        skb->ip_summed = CHECKSUM_NONE;
-    }
-    dst_release(skb->dst);
-    skb->dst = NULL;
-    nf_reset(skb);
-#ifdef CONFIG_BRIDGE_NETFILTER
-    if(skb->nf_bridge){
-        // Stop the eth header being clobbered by nf_bridge_maybe_copy_header().
-        _nf_bridge_save_header(skb);
-    }
-#endif
-#endif // __KERNEL__
+    skb->nh.raw = skb_pull_vn(skb, ETH_HLEN);
+    skb->h.raw = newskb->nh.raw + sizeof(struct iphdr);
 
-    dprintf("> Unpacked srcaddr=" IPFMT " vnet=%s srcmac=" MACFMT " dstmac=" MACFMT "\n",
+    dprintf("> Unpacked srcaddr=" IPFMT " dstaddr=" IPFMT " vnet=%s srcmac=" MACFMT " dstmac=" MACFMT "\n",
             NIPQUAD(skb->nh.iph->saddr),
+            NIPQUAD(skb->nh.iph->daddr),
             VnetId_ntoa(&vnet, vnetbuf),
             MAC6TUPLE(eth->h_source),
             MAC6TUPLE(eth->h_dest));
index d8bd34c3acd4c4557044aff83a4bda88b4f20d3f..4c71adf8c6270cacbaf599c3a5bf18ad4a38025b 100644 (file)
@@ -67,6 +67,21 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
 
 #endif
 
+/*
+ * It's a copy from {kernel}/include/linux/skbuff.h func '__skb_pull' and 'skb_pull'
+ * to aviodthe BUG_ON when pulling into the data (getting forwarded ip-frames)
+ */
+static inline unsigned char *__skb_pull_vn(struct sk_buff *skb, unsigned int len)
+{
+        skb->len -= len;
+        //BUG_ON(skb->len < skb->data_len);
+        return skb->data += len;
+}
+static inline unsigned char *skb_pull_vn(struct sk_buff *skb, unsigned int len)
+{
+        return unlikely(len > skb->len) ? NULL : __skb_pull_vn(skb, len);
+}
+
 
 #ifdef __KERNEL__
 
index aefbd43d432e1efb056be52bdb9a430e19edda20..3dad41768731f761a6f4a9188755231bb58852d5 100644 (file)
@@ -1365,7 +1365,7 @@ int varp_handle_message(struct sk_buff *skb){
             goto exit;
         }
     }
-    varph = (void*)skb_pull(skb, sizeof(struct udphdr));
+    varph = (void*)skb_pull_vn(skb, sizeof(struct udphdr));
     if(skb->len < sizeof(struct VnetMsgHdr)){
         wprintf("> Varp msg too short: %d < %d\n", skb->len, sizeof(struct VnetMsgHdr));
         goto exit;
@@ -1378,11 +1378,11 @@ int varp_handle_message(struct sk_buff *skb){
         }
         break;
     case VUDP_ID: // Etherip-in-udp packet.
-        skb_pull(skb, sizeof(struct VnetMsgHdr));
+        skb_pull_vn(skb, sizeof(struct VnetMsgHdr));
         err = etherip_protocol_recv(skb);
         goto exit;
     case VFWD_ID: // Forwarded.
-        skb_pull(skb, sizeof(struct VnetMsgHdr));
+        skb_pull_vn(skb, sizeof(struct VnetMsgHdr));
         err = vnet_forward_recv(skb);
         goto exit;
     default:
index 2064d7890dc6a247ec8a43b09f3cd627243f9299..74a55c458208b6f7de8f07897ef4d079975a589b 100644 (file)
@@ -186,7 +186,7 @@ static int VnetPeer_forward(VnetPeer *peer, struct sk_buff *fwdskb){
     printk("\nWrapped packet:\n");
     print_iphdr(__FUNCTION__, skb);
     print_udphdr(__FUNCTION__, skb);
-    skb_print_bits(__FUNCTION__, skb, 0, 0 * skb->len);
+    skb_print_bits(__FUNCTION__, skb, 0, skb->len);
 #endif
 
     err = _skb_xmit(skb, saddr);
@@ -304,7 +304,7 @@ int vnet_forward_recv(struct sk_buff *skb){
     peer->rx_packets++;
     skb->mac.raw = NULL;
     skb->nh.raw = skb->data;
-    skb->h.raw = (void*)(skb->nh.iph + 1);
+    skb->h.raw = skb->data + sizeof(struct iphdr);
     if(!skb->nh.iph->saddr){
         skb->nh.iph->saddr = addr.u.ip4.s_addr;
     }
@@ -328,12 +328,17 @@ int vnet_forward_recv(struct sk_buff *skb){
 
     // Handle (a copy of) it ourselves, because
     // if it is looped-back by xmit it will be ignored.
-    //recvskb = skb_clone(skb, GFP_ATOMIC);
-    recvskb = pskb_copy(skb, GFP_ATOMIC);
+    recvskb = alloc_skb(skb->len, GFP_ATOMIC);
     if(recvskb){
+        recvskb->protocol = htons(ETH_P_IP);
+
+        recvskb->nh.raw = skb_put(recvskb, skb->len);
+        recvskb->h.raw = recvskb->data + sizeof(struct iphdr); 
+        skb_copy_bits(skb, 0, recvskb->data, skb->len);
+        
         // Data points at the unwrapped iphdr, but varp_handle_message()
         // expects it to point at the udphdr, so pull.
-        skb_pull(recvskb, sizeof(struct iphdr));
+        skb_pull_vn(recvskb, sizeof(struct iphdr));
         if(varp_handle_message(recvskb) <= 0){
             kfree_skb(recvskb);
         }